﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace Battle
{
    public class Bullet_Ray : MonoBehaviour, IBullet
    {
        protected const float RotateSpeed = 3f;

        public bool RayActive
        {
            get => gameObject.activeSelf;
            set
            {
                if (gameObject.activeSelf != value)
                    gameObject.SetActive(value);
            }
        }

        protected IBulletHitHandler hitHandler;
        protected IEnemyTargetGetter targetGetter;

        protected LineRenderer line;
        protected TextMesh text;

        [SerializeField,ReadOnly]
        protected float fRayWidth, fRayLength, fPercent;
        protected Vector3 vCurDir;

        protected ICanHitObj target;
        protected Vector3 LineEndPos => vCurDir.normalized * fRayLength + transform.position;

        public Vector3 Pos => transform.position;

        public ST_BulletData BulletData { get; protected set; }

        private void Awake()
        {
            line = GetComponentInChildren<LineRenderer>();
            text = GetComponentInChildren<TextMesh>();

            vCurDir = Vector3.up;
        }
        private void Update()
        {
            if (target != null && !target.IsDeath)
            {
                vCurDir = Vector3.Lerp(vCurDir, (target.Pos - transform.position).normalized, RotateSpeed * Time.deltaTime);

                line.SetPosition(1, LineEndPos);
            }
        }

        public void InitBulletData(ST_BulletData bulletData, IBulletHitHandler hitHandler, IEnemyTargetGetter targetGetter)
        {
            this.BulletData = bulletData;
            this.hitHandler = hitHandler;
            this.targetGetter = targetGetter;

            transform.position = bulletData.vBornPos;
            line.SetPosition(0, bulletData.vBornPos);
        }
        
        public void SetRaySize(float length, float width)
        {
            fRayLength = length;
            fRayWidth = width;
        }

        public void SetRayPercent(float percent)
        {
            fPercent = percent;

            float width = (1 + percent / 5f) * fRayWidth;
            //Debug.Log($"width:{width}  percent:{percent}  fRayWidth:{fRayWidth}");
            line.startWidth = width;
            line.endWidth = width;

            text.text = $"{(int)(percent * 100f)}%";
        }

        public void SetTarget(ICanHitObj canHitObj, bool waitLastTarget = true)
        {
            //等上一个目标
            if (waitLastTarget && target != null && !target.IsDeath) return;

            target = canHitObj;
        }

        public void Attack()
        {
            //TODO 射线带宽度
            Vector3 start = line.GetPosition(0), end = line.GetPosition(1);
            var arrHitInfo =Physics2D.RaycastAll(start, end-start, fRayLength);

            for (int i = 0; i < arrHitInfo.Length; i++)
            {
                ICanHitObj canHitObj = arrHitInfo[i].collider.GetComponentInParent<ICanHitObj>();

                if (canHitObj != null)
                {
                    HitObj(canHitObj);
                }
            }
        }

        protected void HitObj(ICanHitObj obj)
        {
            if (hitHandler != null)
            {
                hitHandler?.OnHit(this, obj);
            }
            else
            {
                //需要优化，不能每次调用都重新算
                obj.OnHit(new ST_HitActionData()
                {
                    fAtk= (int)(BulletData.nDmg * fPercent),
                    nRepelNum= (int)(BulletData.nRepelNum * fPercent),
                    vRepelDir=LineEndPos-transform.position,
                });
            }
        }

        public void DestorySelf()
        {
            //TODO 内存池
            Destroy(gameObject);
        }
    }
}
